//////////////////////////////////////////////////////
// 程序名称：绘制B样条曲面
// 功 能：绘制两个B样条曲面
// 编译环境：Visual Studio 2017，EasyX_20190219(beta)
// 作 者：xyqlx<mxxyqlx@qq.com>
// 最后修改：2019-5-25
#include <conio.h>
#include <graphics.h>
#include <cmath>
int offx = 0, offy = 0;
void Point(int x, int y)
{
	putpixel(x + offx, y + offy, RED);
}
void Draw(int p[4][4][2])
{
	float u, w, prec = 0.01f;

	for (u = 0.0f; u < 1.0f; u += prec)
	{
		for (w = 0.0f; w < 1.0f; w += prec)
		{
			float u3(u * u * u), u2(u * u), u1(u);
			float temp[4], res[4][2];
			temp[0] = (-u3 + 3.0f * u2 - 3.0f * u1 + 1.0f) / 6.0f;
			temp[1] = (3.0f * u3 + -6.0f * u2 + 4.0f) / 6.0f;
			temp[2] = (-3.0f * u3 + 3.0f * u2 + 3.0f * u1 + 1.0f) / 6.0f;
			temp[3] = u3 / 6.0f;
			for (int i = 0; i < 4; ++i)
			{
				res[i][0] = res[i][1] = 0.0f;
				for (int j = 0; j < 4; ++j)
				{
					res[i][0] += temp[j] * p[j][i][0];
					res[i][1] += temp[j] * p[j][i][1];
				}
			}
			for (int i = 0; i < 2; ++i)
			{
				temp[0] = (-res[3][i] + 3.0f * res[2][i] - 3.0f * res[1][i] + 1.0f * res[0][i]) / 6.0f;
				temp[1] = (3.0f * res[3][i] + -6.0f * res[2][i] + 3.0f * res[1][i]) / 6.0f;
				temp[2] = (-3.0f * res[3][i] + 3.0f * res[1][i]) / 6.0f;
				temp[3] = (res[3][i] + 4.0f * res[2][i] + res[1][i]) / 6.0f;
				for (int j = 0; j < 4; ++j)
					res[j][i] = temp[j];
			}
			Point(res[0][0] * w * w * w + res[1][0] * w * w + res[2][0] * w + res[3][0], res[0][1] * w * w * w + res[1][1] * w * w + res[2][1] * w + res[3][1]);
		}
	}
}
int main()
{
	// 创建绘图窗口，大小为 640x480 像素
	initgraph(640, 480);
	//填充背景为白色
	setbkcolor(WHITE);
	cleardevice();
	//开始绘制
	int p1[4][4][2] = {{{0, 0}, {160, 50}, {480, 30}, {640, 0}},
					   {{0, 120}, {0, 0}, {600, 10}, {640, 120}},
					   {{0, 240}, {700, 700}, {-600, 240}, {640, 240}},
					   {{0, 480}, {160, 400}, {320, 360}, {480, 360}}};

	int p2[4][4][2] = {{{0, 0}, {160, 50}, {480, 30}, {640, 0}},
					   {{0, 120}, {360, 0}, {600, 10}, {640, 120}},
					   {{0, 240}, {300, 700}, {500, 240}, {640, 240}},
					   {{0, 480}, {160, 400}, {320, 360}, {480, 360}}};

	Draw(p1);
	offx = 30;
	Draw(p2);
	//结束绘制
	_getch();	 // 按任意键继续
	closegraph(); // 关闭绘图窗口
	return 0;
}